//
// Created by 33145 on 2023/3/29.
//
#include "ws_server.h"
#include "sylar/log.h"

namespace sylar {
  namespace http {

    static sylar::Logger::ptr g_logger = SYLAR_LOG_NAME("system");

    WSServer::WSServer(sylar::IOManager* worker, sylar::IOManager* io_worker, sylar::IOManager* accept_worker)
            :TcpServer(worker, io_worker, accept_worker) {
      m_dispatch.reset(new WSServletDispatch);
      m_type = "websocket_server";
    }

    void WSServer::handleClient(Socket::ptr client) {
      SYLAR_LOG_DEBUG(g_logger) << "handleClient\n" << *client;
      WSSession::ptr session(new WSSession(client));
      do {
        /// 处理时会先检查协议是否被升级为WebSocket，检查完会回复一个rsp
        /// WebSocket的特点，两端只需要交换一次HTTP请求就可以一直发送消息
        /// 也对应了交互性强的需求（消息比较短，使用很长的HTTP头进行消息传递，得不偿失）
        HttpRequest::ptr header = session->handleShake();
        if(!header) {
          SYLAR_LOG_DEBUG(g_logger) << "handleShake error";
          break;
        }
        WSServlet::ptr servlet = m_dispatch->getWSServlet(header->getPath());
        if(!servlet) {
          SYLAR_LOG_DEBUG(g_logger) << "no match WSServlet";
          break;
        }
        /// 用来处理刚建立连接时的自定义回调
        int rt = servlet->onConnect(header, session);
        if(rt) {
          SYLAR_LOG_DEBUG(g_logger) << "onConnect return " << rt;
          break;
        }
        while(true) {
          /// 如果两分钟客户端未收到消息，则会向服务器发送断开连接的请求
          auto msg = session->recvMessage();
          // SYLAR_LOG_DEBUG(g_logger) << "recv some message: " << msg->getData();
          if(!msg) {
            break;
          }
          /// 处理业务
          rt = servlet->handle(header, msg, session);
          if(rt) {
            SYLAR_LOG_DEBUG(g_logger) << "handle return " << rt;
            break;
          }
        }
        /// 用来处理连接断开时的自定义回调
        servlet->onClose(header, session);
      } while(false);
      // SYLAR_LOG_DEBUG(g_logger) << "close";
      session->close();
    }

  }
}